package com.gcloud.mesh.asset.utils.supervisionsystem;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gcloud.mesh.asset.dao.IaasDao;
import com.gcloud.mesh.asset.entity.IaasEntity;
import com.gcloud.mesh.asset.enums.YingZeDeviceType;
import com.gcloud.mesh.header.enums.ResourceSourceType;
import com.gcloud.mesh.header.vo.asset.DeviceItemVo;
import com.gcloud.mesh.header.vo.supplier.YingZeAssetItemVo;
import com.gcloud.mesh.header.vo.supplier.YingZeSupervisionSystemVo;
import com.gcloud.mesh.supplier.dao.SupplierDao;
import com.gcloud.mesh.supplier.entity.SupplierEntity;
import com.gcloud.mesh.utils.SupplierSystemTypeUtil;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
@ConditionalOnProperty(name = "asset.supervision_system", havingValue = "yingze")
public class YingZeSupervisionSystem implements ISupervisionSystem {

	@Autowired
	private SupplierDao supplierDao;

	@Autowired
	private IaasDao iaasDao;

	private static final String TYPE = "supervision_system_yingze";

	private static final String GENERAL = "general";

	@Override
	public <E> List<E> sync(Class clazz) {
		return null;
	}

	@Override
	public void syncDevice(int type) {
		List<SupplierEntity> suppliers = supplierDao.findAll().stream().filter(s -> TYPE.equals(s.getType()))
				.collect(Collectors.toList());
		for (SupplierEntity supplier : suppliers) {
			YingZeSupervisionSystemVo obj = (YingZeSupervisionSystemVo) SupplierSystemTypeUtil
					.getByName(supplier.getType(), supplier.getConfig());
			List<YingZeAssetItemVo> items = listAssets(obj.getHostIp(), obj.getPort());
			Map<String, Object> props = new HashMap<String, Object>();
			props.put("datacenter_id", supplier.getDatacenterId());
			props.put("from", ResourceSourceType.SYNC.getName());
			List<DeviceItemVo> devices = iaasDao.findByProperties(props, DeviceItemVo.class).stream()
					.filter(s -> s.getType() == type).collect(Collectors.toList());
			saveDevice(items, devices, supplier.getDatacenterId());
			updateDevice(items, devices, supplier.getDatacenterId());
			deleteDevice(items, devices);
		}

	}

	@Override
	public void syncNodeAndSwitcher(int type) {
		// TODO Auto-generated method stub

	}

	public List<YingZeAssetItemVo> listAssets(String hostIp, String port) {
		String url = "http://" + hostIp + ":" + port + "/device/list";
		RestTemplate restTemplate = new RestTemplate();
		String res = restTemplate.getForEntity(url, String.class).getBody();
		JSONArray jsonArray = JSONArray.parseArray(res);
		List<YingZeAssetItemVo> assets = new ArrayList<YingZeAssetItemVo>();

		for (int i = 0; i < jsonArray.size(); i++) {
			JSONObject json = jsonArray.getJSONObject(i);
			YingZeAssetItemVo vo = (YingZeAssetItemVo) JSONObject.parseObject(json.toString(), YingZeAssetItemVo.class);
			assets.add(vo);
		}

		return assets;
	}

	private void saveDevice(List<YingZeAssetItemVo> items, List<DeviceItemVo> devices, String datacenterId) {
		List<String> exists = devices.stream().map(s -> s.getName()).collect(Collectors.toList());
		List<YingZeAssetItemVo> newItems = items.stream().filter(s -> !exists.contains(s.getName()))
				.collect(Collectors.toList());
		if (newItems != null) {
			for (YingZeAssetItemVo vo : newItems) {
				IaasEntity iaas = new IaasEntity();
				iaas.setId(UUID.randomUUID().toString());
				iaas.setName(vo.getName());
				iaas.setEsn(GENERAL);
				iaas.setDatacenterId(datacenterId);
				iaas.setCreator(null);
				iaas.setCreateTime(new Date());
				iaas.setDeviceManufacturer(GENERAL);
				iaas.setDeviceModel(GENERAL);
				// iaas.setVisible(true);
				iaas.setFrom(ResourceSourceType.SYNC.getName());

				iaas.setDeviceId(vo.getDeviceID());

				if (YingZeDeviceType.getDeviceTypeByCnName(vo.getName()) != null) {
					iaas.setType(YingZeDeviceType.getDeviceTypeByCnName(vo.getName()).getDeviceType().getNo());
				}

				try {
					iaasDao.save(iaas);
				} catch (Exception e) {
					log.error("save deivce resource from supervision system failed : {}", e.getMessage());
				}
			}
		}
	}

	private void updateDevice(List<YingZeAssetItemVo> items, List<DeviceItemVo> devices, String datacenterId) {

	}

	private void deleteDevice(List<YingZeAssetItemVo> items, List<DeviceItemVo> devices) {
		List<String> exists = items.stream().map( s -> s.getName()).collect(Collectors.toList());
		List<DeviceItemVo> deletes = devices.stream().filter( s -> !exists.contains(s.getName())).collect(Collectors.toList());
		if(deletes != null) {
			for(DeviceItemVo vo: deletes) {
				try {
					iaasDao.deleteById(vo.getId());
				} catch(Exception e) {
					log.error("delete deivce resource from supervision system failed : {}", e.getMessage());
				}
			}
		}
	}

}
